import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Hashtable;

public class Money implements Serializable
{
  private static final String N_A = "N/A";
  private String currencyMnemonic;
  private BigDecimal value;
  private static final BigDecimal ZERO = new BigDecimal("0.0");

  private static final Hashtable zeroMoneys = new Hashtable();

  public static final Money NOT_AVAILABLE = new Money();

  private Money()
  {
    this("N/A", ZERO);
  }

  public Money(String currencyMnemonic, BigDecimal value)
  {
    if ((currencyMnemonic == null) || (value == null))
    {
      throw new NullPointerException("parameter is null");
    }

    this.currencyMnemonic = currencyMnemonic;
    this.value = value;
  }

  public Money(String currencyMnemonic, String value)
  {
    if ((currencyMnemonic == null) || (value == null))
    {
      throw new NullPointerException("parameter is null");
    }

    this.currencyMnemonic = currencyMnemonic;
    this.value = new BigDecimal(value);
  }

  public String getCurrencyMnemonic()
  {
    return this.currencyMnemonic;
  }

  public BigDecimal getValue()
  {
    if (this.value == null)
    {
      this.value = ZERO;
    }

    return this.value;
  }

  public static Money getZeroMoney(String currencyMnemonic)
  {
    if (currencyMnemonic == null)
    {
      return NOT_AVAILABLE;
    }

    Money money = (Money)zeroMoneys.get(currencyMnemonic);

    if (money == null)
    {
      money = new Money(currencyMnemonic, ZERO);
      zeroMoneys.put(currencyMnemonic, money);
    }

    return money;
  }

  public boolean equals(Object anObject)
  {
    if ((anObject != null) && (anObject.getClass() == getClass()))
    {
      return isEqual((Money)anObject);
    }

    return super.equals(anObject);
  }

  public boolean isEqual(Money money)
  {
    Money that = money;

    if ((that == null) || (!that.isAvailable()) || (!isAvailable()))
    {
      return false;
    }

    return (this.currencyMnemonic.equals(that.currencyMnemonic)) && (this.value.compareTo(that.value) == 0);
  }

  public boolean isAvailable()
  {
    return (this.currencyMnemonic != null) && (!this.currencyMnemonic.equals("N/A")) && (this.value != null);
  }

  public boolean isOfSameCurrency(Money money)
  {
    if ((isAvailable()) && (money.isAvailable()))
    {
      return this.currencyMnemonic.equals(money.getCurrencyMnemonic());
    }

    return false;
  }

  public String toString()
  {
    if (!isAvailable())
    {
      return "N/A";
    }

    StringBuffer buff = new StringBuffer(this.currencyMnemonic);
    buff.append(' ');
    buff.append(this.value);

    return buff.toString();
  }
}